package com.serialport.ComAssistant;

import android.util.Log;

import com.serialport.bean.ComBean;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.List;

import android_serialport_api.SerialPort;

/**
 * @author benjaminwan
 *串口辅助工具类
 */
public abstract class SerialHelper{
	private SerialPort mSerialPort;
	private OutputStream mOutputStream;
	private InputStream mInputStream;
	private ReadThread mReadThread;
	private SendThread mSendThread;
	private String sPort="/dev/s3c2410_serial0";
	private int iBaudRate=9600;
	private boolean _isOpen=false;
    boolean readThread_IsRun=true;
    boolean read_IsRun=true;
	private byte[] _bLoopData=new byte[]{0x30};
	private int iDelay=500;
	//----------------------------------------------------
	
	public SerialHelper(String sPort,int iBaudRate){
		this.sPort = sPort;
		this.iBaudRate=iBaudRate;
	}
	public SerialHelper(){
		this("/dev/s3c2410_serial0",9600);
	}
	public SerialHelper(String sPort){
		this(sPort,9600);
	}
	public SerialHelper(String sPort,String sBaudRate){
		this(sPort,Integer.parseInt(sBaudRate));
	}
	//----------------------------------------------------
	public void open() throws SecurityException, IOException,InvalidParameterException{
		mSerialPort =  new SerialPort(new File(sPort), iBaudRate, 0);
		mOutputStream = mSerialPort.getOutputStream();
		mInputStream = mSerialPort.getInputStream();
		read_IsRun = true ;
		mReadThread = new ReadThread();
		mReadThread.start();
		mSendThread = new SendThread();
		mSendThread.setSuspendFlag();
		mSendThread.start();
		_isOpen=true;
	}
	//----------------------------------------------------
	public void close(){
		if (mReadThread != null)
//			mReadThread.interrupt();
		    read_IsRun = false ;
		if (mSerialPort != null) {
			mSerialPort.close();
			mSerialPort = null;
		}
		_isOpen=false;
	}
	//----------------------------------------------------
	public void send(byte[] bOutArray){
		try
		{
			mOutputStream.write(bOutArray);
		} catch (IOException e)
		{
			e.printStackTrace();
		}
	}
	//----------------------------------------------------
	public void sendHex(String sHex){
		byte[] bOutArray = MyFunc.HexToByteArr(sHex);
		send(bOutArray);		
	}
	//----------------------------------------------------
	public void sendTxt(String sTxt){
		byte[] bOutArray =sTxt.getBytes();
		send(bOutArray);		
	}

	/**
	*  包头 4B59
	*/


	private class ReadThread    extends Thread {
		private int contentLen;
		@Override
        public void run() {
            super.run();
            int maxLen = 4028;
        	byte[] buffers = new byte[maxLen];
            int available = 0;
            int currentLength = 0;
            while (read_IsRun) {
                try {
                    available = mInputStream.available();
                    if (available > 0) {
                        if (available > maxLen - currentLength) {
                            available = maxLen - currentLength-1;
                        }
                      int a  =  mInputStream.read(buffers, currentLength, available);
                        currentLength += a;
                    }
                    try
					{
						Thread.sleep(100);//延时50ms
						 Log.i("TY", "6--延时50ms ");
					} catch (InterruptedException e)
					{
						e.printStackTrace();
					}
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
                while (currentLength >= 3 && 2 < currentLength) {
                    if (buffers[0] != 0x4B  || buffers[1] != 0x59 ) {
                        System.arraycopy(buffers, 1, buffers, 0, currentLength-1);
                        currentLength = currentLength -1 ;
                        continue;
                    } else {
                    	contentLen=(int)buffers[2];
					}
                    int factPackLen = contentLen + 4;
                    if (currentLength < factPackLen) {
                        break;
                    }else {
                    	String reString = String.format("%02x", buffers[2]).toUpperCase();
                    	 for (int i = 3; i < factPackLen-1; i++) {
                    		 	reString = reString + String.format("%02x", buffers[i]).toUpperCase();
						}
                    	 Log.i("fff", checkcode_0007(reString)+"==校验位是"+checkcode_0007(String.format("%02x", buffers[factPackLen-1])));
                    	 if (checkcode_0007(reString).equals(String.format("%02x", buffers[factPackLen-1]))) {
                    		 ComBean ComRecData = new ComBean(sPort,buffers,factPackLen);
         					 onDataReceived(ComRecData);
						}

					}
					 if (currentLength >= factPackLen ) {
	                     System.arraycopy(buffers, factPackLen, buffers, 0, currentLength-factPackLen);
	                        currentLength -= (factPackLen);
	                    }
                }
            }
        }
    }
//
//		/**
//		* 包头7589
//		*/
//
//
//	private class ReadThread    extends Thread {
//		private int contentLen;
//		@Override
//		public void run() {
//			super.run();
//			int maxLen = 4028;
//			byte[] buffers = new byte[maxLen];
//			int available = 0;
//			int currentLength = 0;
//			while (read_IsRun) {
//				try {
//					available = mInputStream.available();
//					if (available > 0) {
//						if (available > maxLen - currentLength) {
//							available = maxLen - currentLength-1;
//						}
//						int a  =  mInputStream.read(buffers, currentLength, available);
//						currentLength += a;
//					}
//					try
//					{
//						Thread.sleep(100);//延时50ms
//					} catch (InterruptedException e)
//					{
//						e.printStackTrace();
//					}
//				}
//				catch (Exception e) {
//					e.printStackTrace();
//				}
//				while (currentLength >= 3 && 2 < currentLength) {
//					if (buffers[0] != 0x75  || buffers[1] != 0x89 ) {
//						System.arraycopy(buffers, 1, buffers, 0, currentLength-1);
//						currentLength = currentLength -1 ;
//						continue;
//					} else {
//						contentLen=(int)buffers[2];
//					}
//					int factPackLen = contentLen + 4;
//					if (currentLength < factPackLen) {
//						break;
//					}else {
//						String reString = String.format("%02x", buffers[2]).toUpperCase();
//						for (int i = 3; i < factPackLen-1; i++) {
//							reString = reString + String.format("%02x", buffers[i]).toUpperCase();
//						}
//						if (checkcode_0007(reString).equals(String.format("%02x", buffers[factPackLen-1]))) {
//							ComBean ComRecData = new ComBean(sPort,buffers,factPackLen);
//							onDataReceived(ComRecData);
//						}
//
//					}
//					if (currentLength >= factPackLen ) {
//						System.arraycopy(buffers, factPackLen, buffers, 0, currentLength-factPackLen);
//						currentLength -= (factPackLen);
//					}
//				}
//			}
//		}
//	}

	public static String checkcode_0007(String para){  
		int len = para.length()/2 ;
        String[] dateArr = new String[len];  
        try { 
        	for (int i = 0; i < len; i++) {
        		 dateArr[i] = para.substring(2*i, 2*i+2);  
			}
       } catch (Exception e) {  
           // TODO: handle exception  
       }  
       String code = "00000000";  
       for (int i = 0; i < dateArr.length; i++) {  
               code = xor(code, dateArr[i]);  
       }  
       return code;  
}  
	
	public static String xor(String strHex_X,String strHex_Y){   
	        //将x、y转成二进制形式   
	        String oneString=Integer.toBinaryString(Integer.valueOf(strHex_X,16));  
	        String twoString=Integer.toBinaryString(Integer.valueOf(strHex_Y,16));   
	        String result = "";   
	        //判断是否为8位二进制，否则左补零   
	        if(oneString.length() != 8){   
	        for (int i = oneString.length(); i <8; i++) {   
	        	oneString = "0"+oneString; 
	            }   
	        }
	        if(twoString.length() != 8){   
	        for (int i = twoString.length(); i <8; i++) {   
	        	twoString = "0"+twoString;   
	            }   
	        }
	        //异或运算   
	        for(int i=0;i<oneString.length();i++){   
	        //如果相同位置数相同，则补0，否则补1   
	                if(twoString.charAt(i)==oneString.charAt(i))   
	                    result+="0";   
	                else{   
	                    result+="1";   
	                }   
	            }  
	        return Integer.toHexString(Integer.parseInt(result, 2));
	    }  

	
	
//	private class ReadThread   extends Thread {  
//		private int contentLen;
//		private int cursor;
//		int  count  = 0 ;
//		@Override  
//        public void run() {  
//            super.run();  
//            int maxLen = 4028;
//        	byte[] buffers = new byte[maxLen];  
//            int available = 0;  
//            int currentLength = 0;  
//            while (!isInterrupted()) { 
//                try { 
//                    available = mInputStream.available(); 
//                    if (available > 0) { 
//                        if (available > maxLen - currentLength) {  
//                            available = maxLen - currentLength-1; 
//                        }  
//                        int a  =  mInputStream.read(buffers, 0, available);
//                        if (a!=-1) {
//                        	 currentLength += a;
////                        	 Log.i("this_run", "读取缓存后currentLength"+currentLength);
//                        	  ComBean ComRecData = new ComBean(sPort,buffers,a);
////                              count = count  +1 ;
//          					onDataReceived(ComRecData);
//						}
//                    }  
//                    try
//					{
//						Thread.sleep(1000);//延时50ms
//					} catch (InterruptedException e)
//					{
//						e.printStackTrace();
//					}
//                }  
//                catch (Exception e) {  
//                    e.printStackTrace();  
//                }  
////                cursor = 0;  
////                while (currentLength >= 3 && cursor+2 < currentLength) {  
////                	
////                	Log.i("this_run", "读取线程内循环在运行");
////                    if (buffers[cursor] != 0x4B  || buffers[cursor+1] != 0x59 ) {  
////                        cursor = cursor+1;
////                        System.arraycopy(buffers, cursor, buffers, 0, currentLength-cursor-1);
////                        currentLength = currentLength -1 ;
////                        cursor = 0;  
////                        continue;  
////                    } else {
////                    	contentLen=(int)buffers[cursor+2]; 
////					} 
////                    int factPackLen = contentLen + 2 +1+1;
////                    if (currentLength < cursor + factPackLen-1) { 
////                        break;  
////                    }  
////                    ComBean ComRecData = new ComBean(sPort,buffers,factPackLen);
////                    count = count  +1 ;
////					onDataReceived(ComRecData);
////					 if (currentLength >= factPackLen ) {  
////	                     System.arraycopy(buffers, factPackLen+cursor, buffers, 0, currentLength-factPackLen); 
////	                        currentLength -= (factPackLen);  
////	                        cursor = 0; 
////	                    } 
////                }  
//            }  
//        }  
//    }  
	
	private class ReadThreadaaa  extends Thread {  
		private int contentLen;  
		private int cursor;
		int  count  = 0 ;
		byte[] res_buffers = null;
		@Override  
        public void run() {  
            super.run();  
            int maxLen = 4028;
        	byte[] buffers = new byte[maxLen];  
            int available = 0;  
            int currentLength = 0;  
            while (!isInterrupted()) { 
                try { 
                    available = mInputStream.available(); 
                    if (available > 0) { 
                        if (available > maxLen - currentLength) {  
                            available = maxLen - currentLength-1; 
                        }  
                        mInputStream.read(buffers, currentLength, available); 
                        currentLength += available;
                    }  
                    
                    try
					{
						Thread.sleep(50);//延时50ms
					} catch (InterruptedException e)
					{
						e.printStackTrace();
					}
                }  
                catch (Exception e) {  
                    e.printStackTrace();  
                }  
                cursor = 0;  
                while (currentLength >= 3 && cursor+2 < currentLength) {  
                    if (buffers[cursor] != 0x4B  || buffers[cursor+1] != 0x59 ) {  
                        cursor = cursor+1;
                        continue;  
                    } else {
                    	contentLen=(int)buffers[cursor+2]; 
					} 
                    int factPackLen = contentLen + 4;
                    if (currentLength-cursor <  factPackLen) { 
                    	System.arraycopy(buffers, cursor, buffers, 0, currentLength-cursor); 
                    	currentLength = currentLength-cursor;
                        break;  
                    }else {
						res_buffers = new byte[factPackLen];
						for (int i = 0; i < factPackLen; i++) {
							res_buffers[i] = buffers[cursor+i];
							System.out.print("cursor"+cursor);
//							Log.i("xianshi", cursor+"");
							Log.i("xianshi", res_buffers[i]+"");
						}
					}
                    ComBean ComRecData = new ComBean(sPort,res_buffers,factPackLen);
					onDataReceived(ComRecData);
					System.arraycopy(buffers, cursor+factPackLen, buffers, 0, currentLength-factPackLen-cursor); 
					currentLength = currentLength-factPackLen-cursor;
                }  
            }  
        }  
    }  
	
	private class ReadThreadadad extends Thread {
		@Override
		public void run() {
			super.run();
			while(!isInterrupted()) {
				try
				{
					if (mInputStream == null) return;
					byte[] buffer=new byte[512];
					int size = mInputStream.read(buffer);
					if (size > 0){
						ComBean ComRecData = new ComBean(sPort,buffer,size);
						onDataReceived(ComRecData);
					}
					try
					{
						Thread.sleep(50);//延时50ms
					} catch (InterruptedException e)
					{
						e.printStackTrace();
					}
				} catch (Throwable e)
				{
					e.printStackTrace();
					return;
				}
			}
		}
	}
	
	private class ReadThreadddddd extends Thread {
		@Override
		public void run() {
			super.run();
			while(!isInterrupted()) {
				try
				{
					if (mInputStream == null) return;
					byte[] buffer=new byte[256];
					int size = mInputStream.read(buffer);
					if (size>0){
						ComBean ComRecData = new ComBean(sPort,buffer,size);
						onDataReceived(ComRecData);
					}
					try
					{
						Thread.sleep(50);//延时50ms
					} catch (InterruptedException e)
					{
						e.printStackTrace();
					}
				} catch (Throwable e)
				{
					e.printStackTrace();
					return;
				}
			}
		}
	}
//	private class ReadThread   extends Thread {  
//		private int contentLen;
//		private int cursor;
//		int  count  = 0 ;
//		@Override  
//        public void run() {  
//            super.run();  
//            int maxLen = 4028;
//        	byte[] buffers = new byte[maxLen];  
//            int available = 0;  
//            int currentLength = 0;  
//            while (!isInterrupted()) { 
//                try { 
//                    available = mInputStream.available(); 
//                    if (available > 0) { 
//                        if (available > maxLen - currentLength) {  
//                            available = maxLen - currentLength-1; 
//                        }  
//                        mInputStream.read(buffers, currentLength, available); 
//                        currentLength += available;
//                    }  
//                    try
//					{
//						Thread.sleep(1000);//延时50ms
//						 Log.i("TY", "6--延时50ms ");
//					} catch (InterruptedException e)
//					{
//						e.printStackTrace();
//					}
//                }  
//                catch (Exception e) {  
//                    e.printStackTrace();  
//                }  
//                cursor = 0;  
//                while (currentLength >= 3 && cursor+2 < currentLength) {  
//                    if (buffers[cursor] != 0x4B  || buffers[cursor+1] != 0x59 ) {  
//                        cursor = cursor+1;
//                        continue;  
//                    } else {
//                    	contentLen=(int)buffers[cursor+2]; 
//					} 
//                    int factPackLen = contentLen + 2 +1+1;
//                    if (currentLength < contentLen + factPackLen) { 
//                        break;  
//                    }  
//                    ComBean ComRecData = new ComBean(sPort,buffers,factPackLen);
//                    count = count  +1 ;
//					onDataReceived(ComRecData);
//					 if (currentLength >= factPackLen ) {  
//	                     System.arraycopy(buffers, factPackLen+cursor-1, buffers, 0, currentLength-factPackLen); 
//	                        currentLength -= (factPackLen);  
//	                        cursor = 0; 
//	                    } 
//                }  
//            }  
//        }  
//    }  
	
	//----------------------------------------------------
		private class ReadThreadd extends Thread {
			@Override
			public void run() {
				super.run();
				Log.i("dayin", "ReadThread  ");
				int len  = 0 ;
				boolean not_have_len  = true ;
				boolean find_4B = false ;
				boolean find_59  = false ;
				List<Byte> press1 = new ArrayList<Byte>();
				
				
				while(!isInterrupted()) {
					try
					{
						if (mInputStream == null) return;
						int size = mInputStream.read();
						Log.i("dayin", "读到的数值"+size);
						
						if (size==75) {      
							find_4B = true;
							Log.i("dayin", "读到包头==find_4B"+find_4B+"");
							continue;
						}
						if (size == 89) {               //判断是否59
							if (find_4B) {
								find_59 = true ;
								Log.i("dayin", "读到包头==find_59"+find_59+"");
							}else {
								find_4B =false ;
								find_59 = false ;
								Log.i("dayin",find_4B+""+find_59+"");
							}
							continue ;
						}
						if (find_59 && find_4B && not_have_len) {
							len = size ;
							not_have_len = false  ;
							Log.i("dayin","内容长度len的值为"+len);
						}
						
						if (find_59 && find_4B) {      //读取内容长度
							
							switch (len) {
							case 14:
								press1.add((byte)size);
								break;
							default:
								break;
							}
						}
						
						//生成一个完整的压力包
						if (press1.size() == 15) {
							byte[] buffer=new byte[18];
							buffer[0] = (byte)75 ;
							buffer[1] =(byte)89;
							buffer[2] = (byte)14;
							for (int i = 3; i < buffer.length+3; i++) {
								buffer[i] = press1.get(i);
								Log.i("dayin","打印第"+(i+3)+"个数据"+ buffer[i]+"");
							}
							ComBean ComRecData = new ComBean(sPort,buffer,18);
							onDataReceived(ComRecData);
							press1.clear();
							find_4B = false ;
							find_59 = false ;
							not_have_len = true ;
							try
							{
								Thread.sleep(10);//延时50ms
							} catch (InterruptedException e)
							{
								e.printStackTrace();
							}
						}
						
					} catch (Throwable e)
					{
						e.printStackTrace();
						return;
					}
				}
			}
		}
		
		
	//----------------------------------------------------
	private class ReadThreads extends Thread {
		@Override
		public void run() {
			super.run();
			while(!isInterrupted()) {
				try
				{
					if (mInputStream == null){
						Log.i("comtest", "mInputStream == null");
						return;  //跳出本次循环}
					}
					
					int size ;
					boolean Find_4B  = false ;   //发现包头
					boolean Find_59  = false ;   //发现包头
					boolean Is_Receive_Data =false ; //正在接收包内容
					int data_Len  = 0 ;          //内容长度
					int cour = 0 ;
					byte[] result = null ;
					byte[] buffer=new byte[1];
					byte[] rongqi=new byte[2];
					int available = mInputStream.available();
					Log.i("comtest", "available"+available);
					Log.i("comtest", "!isInterrupted()");
					while (available > 3) {
						Log.i("comtest", "进入循环");
						for (int i = 0; i < available; i++) {
							mInputStream.read(buffer, 0, 1); 
							if (buffer[0]==0x4b) {
								Find_4B = true;
								mInputStream.read(buffer, 0, 1); 
								available = mInputStream.available();
								Log.i("comtest", "buffer[0]==0x4b");
							}
							if (Find_4B && buffer[0]==0x59) {
								Find_59  = true ;
								mInputStream.read(buffer, 0, 1);
								data_Len  = buffer[0];
								result  = new byte[data_Len];
								Is_Receive_Data = true ;
								available = mInputStream.available();
								Log.i("comtest", "Find_4B && buffer[0]==0x59");
							}else {
								Find_4B = false ;
								Find_59  = false ;
							    available = mInputStream.available();
							}
							if (Is_Receive_Data && cour <=data_Len+1) {
								mInputStream.read(buffer, 0, 1);
								result[0]=0x4b ;
								result[1]= 0x59;
								result[2]= (byte) data_Len;
								result[3+cour] = buffer[0];
								cour = cour+1;
								available = mInputStream.available();
								Log.i("comtest", "Is_Receive_Data && cour <=data_Len+1");
							}
							if (cour == data_Len+1) {
								Find_4B = false ;
								Find_59  = false ;
								Is_Receive_Data =false;
								ComBean ComRecData = new ComBean(sPort,result,result.length);
								onDataReceived(ComRecData);
								Log.i("comtest", "cour == data_Len+1");
							}
						}
						
					}
					
					
//					int size = mInputStream.read(buffer);
//					if (size > 0){
//						ComBean ComRecData = new ComBean(sPort,buffer,size);
//						onDataReceived(ComRecData);
//					}
					try
					{
						Thread.sleep(10);//延时50ms
					} catch (InterruptedException e)
					{
						e.printStackTrace();
					}
				} catch (Throwable e)
				{
					e.printStackTrace();
					return;
				}
			}
		}
	}
	//----------------------------------------------------
	private class SendThread extends Thread{
		public boolean suspendFlag = true;// 控制线程的执行
		@Override
		public void run() {
			super.run();
			while(!isInterrupted()) {
				synchronized (this)
				{
					while (suspendFlag)
					{
						try
						{
							wait();
						} catch (InterruptedException e)
						{
							e.printStackTrace();
						}
					}
				}
				send(getbLoopData());
				try
				{
					Thread.sleep(iDelay);
				} catch (InterruptedException e)
				{
					e.printStackTrace();
				}
			}
		}

		//线程暂停
		public void setSuspendFlag() {
		this.suspendFlag = true;
		}
		
		//唤醒线程
		public synchronized void setResume() {
		this.suspendFlag = false;
		notify();
		}
	}
	//----------------------------------------------------
	public int getBaudRate()
	{
		return iBaudRate;
	}
	public boolean setBaudRate(int iBaud)
	{
		if (_isOpen)
		{
			return false;
		} else
		{
			iBaudRate = iBaud;
			return true;
		}
	}
	public boolean setBaudRate(String sBaud)
	{
		int iBaud = Integer.parseInt(sBaud);
		return setBaudRate(iBaud);
	}
	//----------------------------------------------------
	public String getPort()
	{
		return sPort;
	}
	public boolean setPort(String sPort)
	{
		if (_isOpen)
		{
			return false;
		} else
		{
			this.sPort = sPort;
			return true;
		}
	}
	//----------------------------------------------------
	public boolean isOpen()
	{
		return _isOpen;
	}
	//----------------------------------------------------
	public byte[] getbLoopData()
	{
		return _bLoopData;
	}
	//----------------------------------------------------
	public void setbLoopData(byte[] bLoopData)
	{
		this._bLoopData = bLoopData;
	}
	//----------------------------------------------------
	public void setTxtLoopData(String sTxt){
		this._bLoopData = sTxt.getBytes();
	}
	//----------------------------------------------------
	public void setHexLoopData(String sHex){
		this._bLoopData = MyFunc.HexToByteArr(sHex);
	}
	//----------------------------------------------------
	public int getiDelay()
	{
		return iDelay;
	}
	//----------------------------------------------------
	public void setiDelay(int iDelay)
	{
		this.iDelay = iDelay;
	}
	//----------------------------------------------------
	public void startSend()
	{
		if (mSendThread != null)
		{
			mSendThread.setResume();
		}
	}
	//----------------------------------------------------
	public void stopSend()
	{
		if (mSendThread != null)
		{
			mSendThread.setSuspendFlag();
		}
	}
	
	public void conturel_Thread(){
		readThread_IsRun = false;
	}
	//----------------------------------------------------
	protected abstract void onDataReceived(ComBean ComRecData);
}